package com.qihoo.finance.fake.service.impl;

import com.qihoo.finance.fake.dao.FakeDao;
import com.qihoo.finance.fake.entity.FakeEntity;
import com.qihoo.finance.fake.registry.FakeRegistryConfig;
import com.qihoo.finance.fake.service.FakeSourceService;
import com.qihoo.finance.fake.variety.VarietyEnum;
import org.apache.dubbo.common.utils.Assert;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Configuration
@ConditionalOnProperty(name = "fake.provider.source.type", havingValue = "local")
public class FakeLocalSourceServiceImpl implements FakeSourceService, InitializingBean {
    private static Logger logger = LogManager.getLogger(FakeSourceService.class);

    private static final Map<String, FakeEntity> MSF_INTERFACES_MAP = new HashMap<>(6);
    static {
        MSF_INTERFACES_MAP.put("com.qihoo.finance.msf.api.dc.facade.DcFacade#isNotWhitelistService",
                new FakeEntity().setInterfaceName("com.qihoo.finance.msf.api.dc.facade.DcFacade")
                .setInterfaceState(1).setMethodName("isNotWhitelistService")
                .setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety()).setVarietyValue("false"));

        MSF_INTERFACES_MAP.put("com.qihoo.finance.msf.api.dc.facade.DcFacade#isRejectedService",
                new FakeEntity().setInterfaceName("com.qihoo.finance.msf.api.dc.facade.DcFacade")
                .setInterfaceState(1).setMethodName("isRejectedService")
                .setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety()).setVarietyValue("false"));

        MSF_INTERFACES_MAP.put("com.qihoo.finance.msf.api.dc.facade.DcFacade#isPauseConsume",
                new FakeEntity().setInterfaceName("com.qihoo.finance.msf.api.dc.facade.DcFacade")
                .setInterfaceState(1).setMethodName("isPauseConsume")
                .setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety()).setVarietyValue("false"));

        MSF_INTERFACES_MAP.put("com.qihoo.finance.msf.api.dc.facade.DcFacade#getInstanceAndSetOnline",
                new FakeEntity().setInterfaceName("com.qihoo.finance.msf.api.dc.facade.DcFacade")
                .setInterfaceState(1).setMethodName("getInstanceAndSetOnline")
                .setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety()).setVarietyValue("{\"name\":\"fake\"}"));

        MSF_INTERFACES_MAP.put("com.qihoo.finance.msf.api.limit.facade.DubboExecuteLimitFacade#queryMaxActivesEffect",
                new FakeEntity().setInterfaceName("com.qihoo.finance.msf.api.limit.facade.DubboExecuteLimitFacade")
                .setInterfaceState(1).setMethodName("queryMaxActivesEffect")
                .setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety()).setVarietyValue("10000"));

        MSF_INTERFACES_MAP.put("com.qihoo.finance.com.modules.auth.PublicKeyFacade#getEffectivePublicKeys",
                new FakeEntity().setInterfaceName("com.qihoo.finance.com.modules.auth.PublicKeyFacade")
                .setInterfaceState(1).setMethodName("getEffectivePublicKeys")
                .setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety()).setVarietyValue("{\"data\":{\"fake\":[\"fakeKeys1\",\"fakeKeys2\"]},\"flag\":\"S\"}"));

        MSF_INTERFACES_MAP.put("com.qihoo.finance.com.modules.crypto.facade.SensitiveDataSecretKeyFacade#getAllSecretKeys",
                new FakeEntity().setInterfaceName("com.qihoo.finance.com.modules.crypto.facade.SensitiveDataSecretKeyFacade")
                .setInterfaceState(1).setMethodName("getAllSecretKeys")
                .setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety())
                .setVarietyValue("{\"data\":[{\"dateEffective\":1569859200000,\"dateExpired\":4102415999000,\"deleteFlag\":\"N\",\"id\":72,\"name\":\"1e\",\"secretKey\":\"N/tqyYtk738jWxV60QI6AIweEZGT3L+ES53rNDd57CB+3uKjU2JvIpLbdXGZwdkU5PUZaYGuGgjBoObXEo/39F6KEV7u4bQngQxXYTMQQm9KQx4bX0pKxzY6sJ0aNnEm4UbVYkBPOy31zp0orwmm3nKZKJg14rZv5YKEEFTe2lA=\",\"version\":1}],\"flag\":\"S\"}"));
    }

    private final FakeDao fakeDao;

    private final FakeRegistryConfig fakeRegistryConfig;

    public FakeLocalSourceServiceImpl(FakeRegistryConfig config, FakeDao dao) {
        this.fakeRegistryConfig = config;
        this.fakeDao = dao;
    }

    @Override
    public List<FakeEntity> loadAll() {
        List<FakeEntity> dbList = fakeDao.selectFakeBaseDbIp(fakeRegistryConfig.getLocalIp())
                .stream().peek(f -> f.setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety()))
                .collect(Collectors.toList());
        if (fakeRegistryConfig.isExportMsf()) {
            dbList.addAll(MSF_INTERFACES_MAP.values());
        }
        return dbList;
    }

    @Override
    public FakeEntity queryFakeOne(String... str) {
        return MSF_INTERFACES_MAP.getOrDefault(str[0] + "#" + str[1],
                new FakeEntity().setVarietyValue(queryFakeDbIpResult(str[0], str[1], fakeRegistryConfig.getLocalIp()))
                .setVarietyType(VarietyEnum.FIXED_DB_IP.getVariety())
                .setInterfaceName(str[0]).setMethodName(str[1]));
    }

    @Override
    public List<FakeEntity> loadNewFakeList() {
        return fakeDao.selectFakeDbIpByState(fakeRegistryConfig.getLocalIp(), 0);
    }

    @Override
    public int updateState(FakeEntity entity, Integer state) {
        return fakeDao.updateInterfaceStateDbIp(entity.getId(), state);
    }

    @Override
    public List<FakeEntity> loadOfflineFakes() {
        return fakeDao.selectFakeDbIpByState(fakeRegistryConfig.getLocalIp(), 3);
    }

    @Override
    public String queryFakeDbIpResult(String interfaceName, String method, String ip) {
        return MSF_INTERFACES_MAP.getOrDefault(interfaceName + "#" + method, new FakeEntity().setVarietyValue(fakeDao.selectFakeBaseDbIpResult(interfaceName, method, ip))).getVarietyValue();
    }

    @Override
    public String queryFakeVarietyTypeByIp(String ip) {
        return VarietyEnum.FIXED_DB_IP.getVariety();
    }

    @Override
    public void afterPropertiesSet() {
        logger.info("fake local config Ip: {}", fakeRegistryConfig.getLocalIp());
        logger.info("fake local export msf interface: {}", fakeRegistryConfig.isExportMsf());
        Assert.notEmptyString(fakeRegistryConfig.getLocalIp(), "fake local config ip is blank");
    }
}
